package com.ruoyi.hook;

//import org.apache.ibatis.javassist.*;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;


/**
 * @author twilight
 * @since V1.0
 */
public class HookUtil {

    public static void main(String[] args) throws Exception {
        insertAt();
        System.out.println("**************华丽丽的分割线***********");
        //setBody();
    }

    private static void insertAt() throws Exception {
        //用于取得字节码类，必须在当前的classpath中，使用全称
        CtClass ctClass = ClassPool.getDefault().get("com.ruoyi.hook.HelloWorld");

        //需要修改的方法名称
        String mname = "method";
        CtMethod mold = ctClass.getDeclaredMethod(mname);

        mold.insertAt(11,"System.out.println(\"hook\");\n");

        //类已经更改，注意不能使用A a=new A();，因为在同一个classloader中，不允许装载同一个类两次
        HelloWorld a = (HelloWorld) ctClass.toClass().newInstance();
        a.method();
    }

    private static void setBody() throws Exception {
        //用于取得字节码类，必须在当前的classpath中，使用全称
        CtClass ctClass = ClassPool.getDefault().get("com.ruoyi.hook.HelloWorld");

        //需要修改的方法名称
        String mname = "method";
        CtMethod mold = ctClass.getDeclaredMethod(mname);


        //修改原有的方法名称
        String nname = mname + "$impl";
        mold.setName(nname);

        //创建新的方法，复制原来的方法
        CtMethod mnew = CtNewMethod.copy(mold, mname, ctClass, null);

        //主要的注入代码
        StringBuffer body = new StringBuffer();
        body.append("{\n System.out.println(\"start\");\n");

        //调用原有代码，类似于method();($$)表示所有的参数
        body.append(nname + "($$);\n");
        body.append("System.out.println(\"end\");\n");
        body.append("}");

        //替换新方法
        mnew.setBody(body.toString());


        //增加新方法
        ctClass.addMethod(mnew);

        //类已经更改，注意不能使用A a=new A();，因为在同一个classloader中，不允许装载同一个类两次
        HelloWorld a = (HelloWorld) ctClass.toClass().newInstance();
        a.method();
    }
}
